/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.aco.party.security.realm;

import com.aco.party.dao.custom.PermissionDao;
import com.aco.party.dao.custom.RoleDao;
import com.aco.party.dao.custom.UserDao;
import com.aco.party.model.po.Permission;
import com.aco.party.model.po.Role;
import com.aco.party.model.po.User;
import com.aco.party.security.token.OpenIdAuthenticationToken;
import com.aco.party.service.system.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.Sha256CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

@Component
public class JdbcRealm extends AuthorizingRealm {

    private final Logger logger = LoggerFactory.getLogger(JdbcRealm.class);
    @Resource
    private UserDao userDao;

    @Resource
    private RoleDao roleDao;

    @Resource
    private PermissionDao permissionDao;

    @Resource
    private UserService userService;

	public JdbcRealm() {
        //setName("SampleRealm"); //This name must match the name in the User class's getPrincipals() method
        setCredentialsMatcher(new Sha256CredentialsMatcher());
    }

    /**
     * 用户登录验证
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        //使用两种token验证方式
        if(authcToken.getClass().isAssignableFrom(UsernamePasswordToken.class)) {
            UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
            logger.info("普通用户名密码方式登录:[" + token.getUsername() + "]为当前登录对象！");

            User user = userDao.getUserByName(token.getUsername());
            if(user == null){
                user = userDao.getUserByEmail(token.getUsername());
                if(user == null) {
                    logger.info("用户名或者邮箱不存在！");
                    return null;
                }
            }

            if(user.getPassword().equals(new Sha256Hash(new String(token.getPassword())).toHex())) {
                logger.info("普通用户名密码方式登录验证成功！");
                logger.info("jdbcRealm:" + user.getUsername() + "," + user.getPassword());
                return new SimpleAuthenticationInfo(user.getId(), user.getPassword(), getName());
            }else{
                logger.info("普通用户名密码方式登录验证失败！");
                return null;
            }
        }else{
            OpenIdAuthenticationToken token = (OpenIdAuthenticationToken)authcToken;
            logger.info("openId方式登录：" + token.getOpenId());

            User user = userService.findUserByOpenId(token.getOpenId());
            if(user != null){
                logger.info("openId方式登录验证成功！");
                logger.info("jdbcRealm:" + user.getUsername() + "," + user.getPassword());
                return new SimpleAuthenticationInfo(user.getId(), user.getPassword(), getName());
            } else {
                logger.info("openId方式登录验证失败！");
                return null;
            }
        }
    }

    /**
     * 用户授权验证
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    	logger.info("=---------------获取用户权限===================");
        Long userId = (Long) principals.fromRealm(getName()).iterator().next();
        logger.info("当前登录用户principal:'"+userId);
        User user = userDao.selectByPrimaryKey(userId);
        
        if( user != null ) {
        	System.out.println("==============开始获取用户权限===================");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            List<Role> roleList = roleDao.getRolesByUser(user.getId());
            if(roleList != null) {
                for (Role role : roleList) {
                    logger.info(user.getUsername() + "角色：" + role.getName());
                    info.addRole(role.getName());
                    Set<String> stringPermissions = new HashSet<String>();
                    List<Permission> permissions = permissionDao.getPermissionsByRoleId(role.getId());
                    for (Iterator<Permission> iterator = permissions.iterator(); iterator
                            .hasNext(); ) {
                        String stringPermission = iterator.next().getRealm();
                        stringPermissions.add(stringPermission);
                        logger.info(user.getUsername() + "权限：" + stringPermission);
                    }
                    info.addStringPermissions(stringPermissions);
                }
            }
            logger.info("=============结束获取用户权=========================");
            return info;
            
        } else {
            return null;
        }
    }

}

